package com.view.speelveld;

import java.util.Observable;
import java.util.Observer;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.widget.Toast;

import com.example.project_speelveld.R;
import com.model.speelveld.AirTower;
import com.model.speelveld.EarthTower;
import com.model.speelveld.FireTower;
import com.model.speelveld.GameModel;
import com.model.speelveld.Level;
import com.model.speelveld.Path;
import com.model.speelveld.Stone;
import com.model.speelveld.Tower;
import com.model.speelveld.WaterTower;
import com.model.speelveld.WaveTime;
import com.model.speelveld.monsters.Monster;
import com.model.speelveld.monsters.NormalMonster;


public class GameView extends TileView implements Observer {
	
	private GameObject [][] gameBoard;
	private static final int NROFDRAWABLES = 8;
	public static final int FIRETOWER = 1;
	public static final int WATERTOWER = 2;
	public static final int AIRTOWER = 3;
	public static final int EARTHTOWER = 4;
	public static final int NORMAL_MONSTER = 5;
	public static final int PATH = 6;
	public static final int CELL = 7;
	public static final int STONE = 8;
	public static int toAdd = CELL;
	public static int toSpawn = NORMAL_MONSTER;
	private GameModel gameModel;
	private Level route;
	private WaveTime waveTimer;
	public static boolean updateStatusBar = false;
	private GameView gameview = this;
	
	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initGameView();
	}
	public GameView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initGameView();
	}
	private void initGameView() {
		waveTimer = new WaveTime(5000);
		setFocusable(true);
		waveTimer.addObserver(this);
		initNewGame();
		
	}
	
	public void setGameModel(GameModel gameModel)
	{
		this.gameModel = gameModel;
	}
	

	private void initNewGame() {
		// TODO Auto-generated method stub
		gameBoard = new GameObject [mXTileCount][mYTileCount];
		for (int i = 0 ; i< mXTileCount; i++)
			for (int j = 0; j < mYTileCount; j++)
			{
			
					gameBoard[i][j] = new GameObject(CELL);
				
				
			}
				
		resetTiles(NROFDRAWABLES +1);
		Resources r = this.getContext().getResources();

		resetTiles(NROFDRAWABLES + 1); /* zero (0) is used for empty */
		
		loadTile(FIRETOWER , r.getDrawable(R.drawable.fire));
		loadTile(WATERTOWER, r.getDrawable(R.drawable.water));
		loadTile(AIRTOWER, r.getDrawable(R.drawable.air));
		loadTile(EARTHTOWER, r.getDrawable(R.drawable.earth));
		loadTile(CELL, r.getDrawable(R.drawable.grass));
		loadTile(PATH, r.getDrawable(R.drawable.path));
		loadTile(NORMAL_MONSTER, r.getDrawable(R.drawable.normal2monster));
		loadTile(STONE, r.getDrawable(R.drawable.stone));
		
		gameBoard[6][1] = new Stone();	
		gameBoard[5][3] = new Stone();	
		gameBoard[7][4] = new Stone();	
		route = new Level();
		route.generateLevel();
		for(Path p: route.getRoute())
		{
			gameBoard[p.getX()][p.getY()] = new Level();
		}
		
		gameBoard[0][0] = new GameObject(CELL); /* just a start */
		
		

		updateField(); 
		invalidate(); 
		
		
	}
	public void updateField() {
		for (int i=0; i< mXTileCount; i++)
			for (int j = 0; j<mYTileCount; j++){
				if (gameBoard[i][j] == null) {
					setTile(CELL, i,j); /* background tile */
				} else {
					setTile(gameBoard[i][j].getTileId(),i,j);
				}
			}

		
	}
	
	@Override
	public void onSizeChanged(int w, int h, int oldw, int oldh){
        super.onSizeChanged(w,h,oldw, oldh);
        initNewGame();
   }

	//@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	@Override
	public void touched(int x, int y){
		//Als de locatie op het speelveld van het type Tower is.
		if(gameBoard[x][y] instanceof Tower)
		{
			
			Tower_Menu towerMenu = (Tower_Menu)((Activity)getContext()).findViewById(R.id.towerMenu1);
			towerMenu.setUpgradeMenuVisible((Tower)gameBoard[x][y]);
			toAdd = CELL;
		}
		else if (gameBoard[x][y] instanceof Stone)
		{
			Toast toast = Toast.makeText(getContext(), "Mag niet!", Toast.LENGTH_SHORT);
			toast.show();
		}
		//Als de locatie op het speelveld van het type Level is.
		else if(!( gameBoard[x][y]  instanceof Level))
		{
			//Switch keuze uit welke toren die moet toevoegen.
			switch(toAdd)
			{
				//Als toAdd FIRETOWER/WATERTOWER/AIRTOWER/EARTHTOWER is dat respectievelijke toren toevoegen.
				case FIRETOWER:
					FireTower ft = new FireTower(x, y, 1,  130, 120, this.gameBoard);
					if(gameModel.buyCheck(ft.getValue()))
					{
						gameBoard[x][y] = ft;
						gameModel.removeMoney(ft.getValue());
						ft.setRangePath(route.getInRangePath(ft));
					}
					else
					{
						Toast toast = Toast.makeText(getContext(), "Need more money!", Toast.LENGTH_SHORT);
						toast.show();
					}
					break;
				case WATERTOWER: 
					WaterTower wt = new WaterTower(x, y, 2, 120, 60, this.gameBoard);
					if(gameModel.buyCheck(wt.getValue()))
					{
						gameBoard[x][y] = wt;
						gameModel.removeMoney(wt.getValue());
						wt.setRangePath(route.getInRangePath(wt));
					}
					else
					{
						Toast toast = Toast.makeText(getContext(), "Need more money!", Toast.LENGTH_SHORT);
						toast.show();
					}
					break;
				case AIRTOWER: 
					AirTower at = new AirTower(x, y, 1,  100, 100, this.gameBoard);
					if(gameModel.buyCheck(at.getValue()))
					{ 	
						gameBoard[x][y] = at;
						gameModel.removeMoney(at.getValue());
						at.setRangePath(route.getInRangePath(at));
					}
					else
					{
						Toast toast = Toast.makeText(getContext(), "Need more money!", Toast.LENGTH_SHORT);
						toast.show();
					}
					break;
				case EARTHTOWER: 
					EarthTower et = new EarthTower(x, y, 2, 110, 80, this.gameBoard);
					if(gameModel.buyCheck(et.getValue()))
					{
						gameBoard[x][y] = et;
						gameModel.removeMoney(et.getValue());
						et.setRangePath(route.getInRangePath(et));
					}
					else
					{
						Toast toast = Toast.makeText(getContext(), "Need more money!", Toast.LENGTH_SHORT);
						toast.show();
					}
					break;
				default : break;
			}
		}
		
		//Update en repaint.
		updateField(); /* update the view */
		invalidate(); /* tell Android the view has to be redrawn */
	}
	
	public void newWave()
	{
		//Als waveNumber 5 is.
		if(gameModel.getWaveNumber() == 4)
		{
			//Verhoog het level en reset waveNumber.
			gameModel.addLevel();
			gameModel.resetWave();
		}
		
		//WaveNumber omhoog.
		gameModel.nextWave();
		
		//Switch op waveNumber
		switch(gameModel.getWaveNumber())
		{
			//Roteer tussen Normaal/snel/langzaam/boss monsters voordat het level omhoog gaat.
			case 1: 
				toSpawn = NORMAL_MONSTER;
				MonsterTimer mt = new MonsterTimer(18000, 1800); 
				mt.start();
				break;
			case 2:
				toSpawn = NORMAL_MONSTER;
				MonsterTimer mt1 = new MonsterTimer(18000, 1800); 
				mt1.start();
				break;
			case 3:
				toSpawn = NORMAL_MONSTER;
				MonsterTimer mt2 = new MonsterTimer(18000, 1800); 
				mt2.start();
				break;
			case 4:

				toSpawn = NORMAL_MONSTER;
				MonsterTimer mt3 = new MonsterTimer(18000, 1800); 
				mt3.start();
				break;
			default: break;
		}
		
		//Update en repaint.
		updateField();
		postInvalidate();
	}
	
	@Override
	public void update(Observable o, Object arg1) {
		if(o instanceof WaveTime)
		{
			waveTimer.setTimeMs(35000);
			newWave();
		}
	}
	
	
	public void moveMonster(Monster m)
	{
		gameBoard[m.getPosition().getX()][m.getPosition().getY()] = m;
		gameBoard[route.getPrevPath(m.getPosition()).getX()][route.getPrevPath(m.getPosition()).getY()] = m.getPosition();
		updateField();
		invalidate();
	}
	
	public void deleteMonster(Monster m)
	{
		gameBoard[route.getEndPostion().getX()][route.getEndPostion().getY()] = route.getEndPostion();
		m = null;
		updateField();
		invalidate();

	}
	
		class MonsterTimer extends CountDownTimer
		{

			public MonsterTimer(long millisInFuture, long countDownInterval) {
				super(millisInFuture, countDownInterval);
				// TODO Auto-generated constructor stub
			}

			@Override
			public void onFinish() {
				onTick(0);
				
			}

			@Override
			public void onTick(long millisUntilFinished) {
				switch(toSpawn)
				{
					case NORMAL_MONSTER: gameBoard[route.getStartPosition().getX()][route.getStartPosition().getY()] = new NormalMonster(gameModel.getLevel(), gameview, route, gameModel); break;
					//case andere monsters spawnen
					default: break;
				}
				
				updateField();
				postInvalidate();
				
			}
			
		}
}


